package com.glSto.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.glSto.domain.GoodsIssueData;
import com.glSto.domain.GoodsIssueResponse;
import com.glSto.service.GoodsIssueService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@Service
public class GoodsIssueServiceImpl implements GoodsIssueService {

    private static final Logger log = LoggerFactory.getLogger(GoodsIssueServiceImpl.class);

    @Resource
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;  // 使用命名参数模板，避免顺序错误

    @Resource
    private ObjectMapper objectMapper;  // JSON解析工具

    /**
     * 处理出库数据：存在则更新，不存在则插入
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String handleGoodsIssueData(String requestBody) throws Exception {
        log.info("开始处理出库数据，请求体长度: {}", requestBody.length());

        try {
            // 1. 解析JSON为实体对象
            GoodsIssueResponse request = objectMapper.readValue(requestBody, GoodsIssueResponse.class);
            GoodsIssueResponse.ImMessage imMessage = request.getIM_MESSAGE();
            List<GoodsIssueResponse.EtData> etDataList = request.getET_DATA();

            if (etDataList == null || etDataList.isEmpty()) {
                log.info("出库明细列表为空，未处理任何数据");
                return "接收成功，但出库明细为空，未存储数据";
            }

            int successCount = 0;
            for (GoodsIssueResponse.EtData etData : etDataList) {
                // 校验关键字段
                if (etData.getAUFNR() == null || etData.getAUFNR().trim().isEmpty() ||
                        etData.getMATNR() == null || etData.getMATNR().trim().isEmpty()) {
                    log.warn("跳过无效出库明细：AUFNR={}, MATNR={}（关键字段为空）",
                            etData.getAUFNR(), etData.getMATNR());
                    continue;
                }

                // 2. 检查数据是否存在（通过生产订单号+物资编码）
                boolean exists = checkDataExists(etData.getAUFNR(), etData.getMATNR());

                // 3. 转换数据（将EtData和ImMessage转换为GoodsIssueData）
                GoodsIssueData data = convertToGoodsIssueData(etData, imMessage);

                // 4. 存在则更新，不存在则插入
                if (exists) {
                    updateData(data);
                    log.info("更新出库明细成功：AUFNR={}, MATNR={}", etData.getAUFNR(), etData.getMATNR());
                } else {
                    insertData(data);
                    log.info("插入出库明细成功：AUFNR={}, MATNR={}", etData.getAUFNR(), etData.getMATNR());
                }
                successCount++;
            }

            log.info("出库数据处理完成，共接收{}条，成功处理{}条", etDataList.size(), successCount);
            return String.format("数据接收成功，共接收 %d 条出库明细，成功处理 %d 条（新增或更新）",
                    etDataList.size(), successCount);
        } catch (Exception e) {
            log.error("处理出库数据发生异常", e);
            throw e;  // 抛出异常触发事务回滚
        }
    }

    /**
     * 检查数据是否存在
     */
    private boolean checkDataExists(String aufnr, String matnr) {
        String sql = "SELECT COUNT(*) FROM ERP_GOODS_ISSUE WHERE AUFNR = :aufnr AND MATNR = :matnr";

        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("aufnr", aufnr);
        params.addValue("matnr", matnr);

        Integer count = namedParameterJdbcTemplate.queryForObject(sql, params, Integer.class);
        return count != null && count > 0;
    }

    /**
     * 插入新数据
     */
    private void insertData(GoodsIssueData data) {
        String sql = "INSERT INTO ERP_GOODS_ISSUE (" +
                "AUFNR, MATNR, MAKTX, MENGE, DMBTR, " +
                "IM_GUID, SEND_TIME, SENDER, SEND_CFID, " +
                "RECEIVER, RECEIVE_IFID, RECEIVE_METHOD, " +
                "SEND_SYSTEM_ID, PROXY_ID, MANDT, SEND_OPERATOR, SPRAS, " +
                "CREATE_TIME, UPDATE_TIME" +  // 增加创建时间和更新时间
                ") VALUES (:aufnr, :matnr, :maktx, :menge, :dmbtr, " +
                ":imGuid, :sendTime, :sender, :sendCfid, " +
                ":receiver, :receiveIfid, :receiveMethod, " +
                ":sendSystemId, :proxyId, :mandt, :sendOperator, :spras, " +
                "SYSDATE, SYSDATE)";  // 使用Oracle的SYSDATE函数

        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("aufnr", data.getAufnr());
        params.addValue("matnr", data.getMatnr());
        params.addValue("maktx", data.getMaktx());
        params.addValue("menge", data.getMenge());
        params.addValue("dmbtr", data.getDmbtr());
        params.addValue("imGuid", data.getImGuid());
        params.addValue("sendTime", data.getSendTime());
        params.addValue("sender", data.getSender());
        params.addValue("sendCfid", data.getSendCfid());
        params.addValue("receiver", data.getReceiver());
        params.addValue("receiveIfid", data.getReceiveIfid());
        params.addValue("receiveMethod", data.getReceiveMethod());
        params.addValue("sendSystemId", data.getSendSystemId());
        params.addValue("proxyId", data.getProxyId());
        params.addValue("mandt", data.getMandt());
        params.addValue("sendOperator", data.getSendOperator());
        params.addValue("spras", data.getSpras());

        namedParameterJdbcTemplate.update(sql, params);
    }

    /**
     * 更新已有数据
     */
    private void updateData(GoodsIssueData data) {
        String sql = "UPDATE ERP_GOODS_ISSUE SET " +
                "MAKTX = :maktx, MENGE = :menge, DMBTR = :dmbtr, " +
                "IM_GUID = :imGuid, SEND_TIME = :sendTime, SENDER = :sender, SEND_CFID = :sendCfid, " +
                "RECEIVER = :receiver, RECEIVE_IFID = :receiveIfid, RECEIVE_METHOD = :receiveMethod, " +
                "SEND_SYSTEM_ID = :sendSystemId, PROXY_ID = :proxyId, MANDT = :mandt, " +
                "SEND_OPERATOR = :sendOperator, SPRAS = :spras, UPDATE_TIME = SYSDATE " +
                "WHERE AUFNR = :aufnr AND MATNR = :matnr";

        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("maktx", data.getMaktx());
        params.addValue("menge", data.getMenge());
        params.addValue("dmbtr", data.getDmbtr());
        params.addValue("imGuid", data.getImGuid());
        params.addValue("sendTime", data.getSendTime());
        params.addValue("sender", data.getSender());
        params.addValue("sendCfid", data.getSendCfid());
        params.addValue("receiver", data.getReceiver());
        params.addValue("receiveIfid", data.getReceiveIfid());
        params.addValue("receiveMethod", data.getReceiveMethod());
        params.addValue("sendSystemId", data.getSendSystemId());
        params.addValue("proxyId", data.getProxyId());
        params.addValue("mandt", data.getMandt());
        params.addValue("sendOperator", data.getSendOperator());
        params.addValue("spras", data.getSpras());
        params.addValue("aufnr", data.getAufnr());
        params.addValue("matnr", data.getMatnr());

        namedParameterJdbcTemplate.update(sql, params);
    }

    /**
     * 将EtData和ImMessage转换为数据库实体
     */
    private GoodsIssueData convertToGoodsIssueData(GoodsIssueResponse.EtData etData, GoodsIssueResponse.ImMessage imMessage) {
        GoodsIssueData data = new GoodsIssueData();
        // 设置明细字段
        data.setAufnr(etData.getAUFNR());
        data.setMatnr(etData.getMATNR());
        data.setMaktx(etData.getMAKTX());
        data.setMenge(etData.getMENGE());
        data.setDmbtr(etData.getDMBTR());

        // 设置消息头字段
        if (imMessage != null) {
            data.setImGuid(imMessage.getIM_GUID());
            data.setSendTime(imMessage.getSEND_TIME());
            data.setSender(imMessage.getSENDER());
            data.setSendCfid(imMessage.getSEND_CFID());
            data.setReceiver(imMessage.getRECEIVER());
            data.setReceiveIfid(imMessage.getRECEIVE_IFID());
            data.setReceiveMethod(imMessage.getRECEIVE_METHOD());
            data.setSendSystemId(imMessage.getSEND_SYSTEM_ID());
            data.setProxyId(imMessage.getPROXY_ID());
            data.setMandt(imMessage.getMANDT());
            data.setSendOperator(imMessage.getSEND_OPERATOR());
            data.setSpras(imMessage.getSPRAS());
        }
        return data;
    }
}
